package ch.ethz.fcl.metrobuzz.data.loader.plan;

import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.newdawn.slick.util.ResourceLoader;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.transit.TransitLine;
import ch.ethz.fcl.metrobuzz.data.transit.TransitRoute;
import ch.ethz.fcl.metrobuzz.tools.MBTools;

public class SingaporeTransitPlanFileLoader {
	private SAXParserFactory parserFactory = SAXParserFactory.newInstance();

	public void load(MBData data, String folder) {
		loadNetwork(
				data,
				ResourceLoader.getResourceAsStream(folder
						+ "/output_network.xml"));
		loadTransitSchedule(
				data,
				ResourceLoader.getResourceAsStream(folder
						+ "/transitSchedule.xml"));

		System.out.println("info: loaded network ("
				+ data.getScene().getNodes().size() + " nodes, "
				+ data.getScene().getEdges().size() + " links, "
				+ data.getPublicTransit().getStops().size() + " stops)");
	}

	private void loadNetwork(final MBData data, InputStream is) {
		try {
			SAXParser parser = parserFactory.newSAXParser();
			parser.parse(is, new DefaultHandler() {
				@Override
				public InputSource resolveEntity(String publicId,
						String systemId) throws org.xml.sax.SAXException,
						java.io.IOException {
					System.out.println("Ignoring: " + publicId + ", "
							+ systemId);
					return new InputSource(new java.io.StringReader(""));
				}

				@Override
				public void startElement(String uri, String localName,
						String name, Attributes attributes) throws SAXException {
					if (name.equals("node")) {
						data.getScene().addNode(attributes);
					} else if (name.equals("link")) {
						data.getScene().addEdge(attributes);
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void loadTransitSchedule(final MBData data, InputStream is) {
		try {
			SAXParser parser = parserFactory.newSAXParser();
			parser.parse(is, new DefaultHandler() {
				@Override
				public InputSource resolveEntity(String publicId,
						String systemId) throws org.xml.sax.SAXException,
						java.io.IOException {
					System.out.println("Ignoring: " + publicId + ", "
							+ systemId);
					return new InputSource(new java.io.StringReader(""));
				}

				TransitLine line = null;
				TransitRoute route = null;

				boolean addMode = false;

				public void startElement(String uri, String localName,
						String name, Attributes attributes) throws SAXException {
					if (name.equals("stopFacility")) {
						data.getPublicTransit().addStops(attributes);
					}
					if (name.equals("transitLine"))
						line = new TransitLine(data, data.getPublicTransit(),
								attributes.getValue("id"));

					if (name.equals("transitRoute")) {
						MBTools.debug("route " + attributes.getValue("id"),
								false);
						if (attributes.getValue("id").contains("-p"))
							route = null;
						else
							route = line.getRoute(attributes.getValue("id"));
					}

					if (name.equals("transportMode") && route != null) {
						addMode = true;
					}

					if (name.equals("stop")) {
						String stopid = attributes.getValue("refId");
						if (route != null)
							route.addStop(data.getPublicTransit()
									.getStopByStopId(stopid));
					}

					if (name.equals("link")) {
						String refid = attributes.getValue("refId");
						if (route != null)
							route.addEdge(data.getScene().getEdge(refid));
					}
				}

				public void endElement(String uri, String localName, String name)
						throws SAXException {
					if (name.equals("transitRoute"))
						if (line != null && route != null) {
							line.addRoute(route);
						}

					if (name.equals("transitLine"))
						if (line != null)
							data.getPublicTransit().addTransitLines(line);
				}

				@Override
				public void characters(char[] ch, int start, int length)
						throws SAXException {
					if (addMode) {
						route.setMode(String.copyValueOf(ch, start, length)
								.trim());
						addMode = false;
					}
				}

			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
